package com.ghp.common.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.convert.Convert;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ghp
 * @title Bean拷贝（浅拷贝）
 * @description
 */
public class BeanConvertorUtils {

    private BeanConvertorUtils() {
    }

    /**
     * 单个Bean拷贝
     *
     * @param source
     * @param clazz
     * @param <V>
     * @return
     */
    public static <V> V copyBean(Object source, Class<V> clazz) {
        //创建目标对象
        V result = null;
        try {
            result = clazz.newInstance();
            //实现属性copy
            BeanUtils.copyProperties(source, result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回结果
        return result;
    }

    /**
     * 多个Bean拷贝
     *
     * @param list
     * @param clazz
     * @param <O>
     * @param <V>
     * @return
     */
    public static <O, V> List<V> copyBeanList(List<O> list, Class<V> clazz) {
        return list.stream()
                .map(o -> copyBean(o, clazz))
                .collect(Collectors.toList());
    }

    /**
     * 将Bean转成Map<String, Object>
     *
     * @param object 目标Bean
     * @param <T>
     * @return
     */
    public static <T> Map<String, Object> beanToMap(T object) {
        return BeanUtil.beanToMap(object, new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) ->
                                Optional.ofNullable(fieldValue)
                                        .map(value -> {
                                            return value.toString();
                                        })
                                        .orElse(null)));
    }


    // 存储基本类型的转换函数
    private static final Map<Class<?>, Function<String, Object>> CONVERTER_MAP = new HashMap<>();

    static {
        // 注册基本类型的转换函数
        CONVERTER_MAP.put(int.class, Integer::parseInt);
        CONVERTER_MAP.put(Integer.class, Integer::valueOf);
        CONVERTER_MAP.put(long.class, Long::parseLong);
        CONVERTER_MAP.put(Long.class, Long::valueOf);
    }

    /**
     * 将Map转换为指定类型的Bean对象
     *
     * @param map       包含数据的Map对象
     * @param beanClass 目标Bean的Class对象
     * @param <T>       目标Bean的类型
     * @return 转换后的Bean对象
     * @throws IllegalAccessException 如果无法访问字段时抛出此异常
     * @throws InstantiationException 如果实例化Bean对象失败时抛出此异常
     */
    public static <T> T mapToBean(Map<Object, Object> map, Class<T> beanClass) throws IllegalAccessException, InstantiationException {
        T bean = beanClass.newInstance();
        Field[] fields = beanClass.getDeclaredFields();
        // 遍历Bean的所有字段
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            // 将map的value赋值给Bean对应的字段
            Object value = map.get(fieldName);
            if (value != null) {
                Object convertedValue = convertValue(value, field.getType());
                field.set(bean, convertedValue);
            }
        }

        return bean;
    }

    /**
     * 将值转换为指定类型
     *
     * @param value      需要转换的值
     * @param targetType 目标类型
     * @return 转换后的结果
     */
    private static Object convertValue(Object value, Class<?> targetType) {
        // 获取当前的字段值的类型
        Function<String, Object> converter = CONVERTER_MAP.get(targetType);
        // 基本类型的转换
        if (converter != null && value instanceof String) {
            return converter.apply(((String) value).replaceAll("^\"|\"$", ""));
        }
        // 日期类型的转换
        if (targetType == Date.class) {
            return Convert.toDate(value);
        }
        // 其他类型的转换
        return Convert.convert(targetType, value);
    }

}
